# -*-coding:utf-8 -*-
from obs import ObsClient
from huaweicloudsdkcore.auth.credentials import \
    BasicCredentials  # Require public dependency:huaweicloudsdkcore
from huaweicloudsdkocr.v1.region.ocr_region import \
    OcrRegion  # Require public dependency:huaweicloudsdkocr
from huaweicloudsdkcore.exceptions import exceptions
from huaweicloudsdkocr.v1 import *
import os
import traceback
from urllib.parse import unquote_plus

default_region = 'cn-north-4'


def check_configuration(context):
    region = context.getUserData('region')
    if not region:
        return 'region is not configured'

    obs_server = context.getUserData('obs_server')
    if not obs_server:
        return 'obs_server is not configured'

    result_bucket = context.getUserData('result_bucket')
    if not result_bucket:
        return 'result_bucket is not configured'

    ak = context.getAccessKey().strip()
    sk = context.getSecretKey().strip()
    if not ak or not sk:
        ak = context.getUserData('ak', '').strip()
        sk = context.getUserData('sk', '').strip()
        if not ak or not sk:
            return 'ak or sk is empty'


def handler(event, context):
    log = context.getLogger()
    result = check_configuration(context)
    if result is not None:
        return result

    records = event.get("Records", None)
    if records is None:
        return 'Records is empty'

    processor = Processor(context)
    try:
        for record in records:
            processor.process(record)
    except:
        log.error("failed to process image, "
                  f"exception：{traceback.format_exc()}")
    finally:
        # 释放资源
        processor.obs_client.close()

    return 'Done'


class Processor:
    def __init__(self, context=None):
        self.log = context.getLogger()
        self.obs_client = new_obs_client(context)
        self.ocr_client = new_ocr_client(context)
        self.image_bucket = None
        self.image_object_key = None
        self.image_url = None
        self.output_object_key = None
        self.result_bucket = context.getUserData('result_bucket')

    def process(self, record):
        # 解析record
        self.analysis_record(record)
        # ocr-健康码识别
        response = self.recognize_health_code()
        if response is None:
            return
        # 返回的内容写入与图片同名的json文件中，然后上传到指定的输出桶
        self.upload_result(response.result)

    def recognize_health_code(self):
        try:
            request = RecognizeHealthCodeRequest()
            request.body = HealthCodeRequestBody(
                url=self.image_url
            )
            return self.ocr_client.recognize_health_code(request)
        except exceptions.ClientRequestException as e:
            self.log.error(f"failed to recognize health code："
                           f"status_code：{e.status_code}, "
                           f"request_id:{e.request_id}, "
                           f"error_code:{e.error_code}. "
                           f"error_msg:{e.error_msg}")
            self.upload_result(e)

    def upload_result(self, result):
        try:
            resp = self.obs_client.putContent(self.result_bucket,
                                              self.output_object_key,
                                              content=result)
            if resp.status < 300:
                self.log.info("succeed to upload result.")
            else:
                self.log.error("failed to upload result, "
                               f"requestId：{resp.requestId} "
                               f"errorCode：{resp.errorCode} "
                               f"errorMessage：{resp.errorMessage}")
        except:
            self.log.error("failed to upload result, "
                           f"exception：{traceback.format_exc()}")

    def analysis_record(self, record):
        region = get_region(record)
        # 提取图片所在的obs桶和key
        (bucket_name, object_key) = get_obs_obj_info(record)
        self.image_bucket = bucket_name
        self.log.info("input bucket_name: %s", bucket_name)
        self.image_object_key = unquote_plus(object_key)
        self.log.info("input object: %s", self.image_object_key)
        # 拼接图片obs访问url
        self.image_url = "https://" + bucket_name + ".obs." + \
                         region + ".myhuaweicloud.com/" + self.image_object_key
        (path, filename) = os.path.split(self.image_object_key)
        (filename, _) = os.path.splitext(filename)
        # 处理结果输出对象
        self.output_object_key = path + filename + ".json"


def get_obs_obj_info(record):
    if 's3' in record:
        s3 = record['s3']
        return (s3['bucket']['name'], s3['object']['key'])
    else:
        obs_info = record['obs']
        return (obs_info['bucket']['name'], obs_info['object']['key'])


def new_obs_client(context):
    return ObsClient(
        access_key_id=context.getAccessKey(),
        secret_access_key=context.getSecretKey(),
        server=context.getUserData('obs_server'),
    )


def new_ocr_client(context):
    credentials = BasicCredentials(context.getAccessKey(),
                                   context.getSecretKey())
    return OcrClient.new_builder() \
        .with_credentials(credentials) \
        .with_region(OcrRegion.value_of(context.getUserData('region'))) \
        .build()


def get_region(record):
    if 'eventRegion' in record:
        return record.get("eventRegion", default_region)
    else:
        return record.get("awsRegion", default_region)
